package org.gikolet.ch2.android.logic;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.gikolet.ch2.data.Board;
import org.gikolet.ch2.data.Category;
import org.gikolet.ch2.io.BoardsReader;
import org.gikolet.ch2.io.BoardsReaderProvider;
import org.gikolet.ch2.io.ReaderType;
import org.gikolet.ch2.logic.BoardsLogic;
import org.gikolet.guice.db.Transactional;
import org.gikolet.util.IOUtils;
import org.gikolet.util.ProgressMonitor;
import org.gikolet.util.Tuple.Tuple2;

import roboguice.inject.ContextScoped;

import com.google.inject.Inject;

@ContextScoped
public class AndroidBoardsLogic implements BoardsLogic {
	@Inject
	BoardsReaderProvider boardsReaderProvider;

	private List<Tuple2<Category, List<Board>>> boards = null;

	@Transactional
	public List<Tuple2<Category, List<Board>>> getBoards() throws IOException {
		System.out.println("b");
		if (this.boards != null) {
			return new ArrayList<Tuple2<Category, List<Board>>>(this.boards);
		}

		List<Tuple2<Category, List<Board>>> categoriesBoards = new ArrayList<Tuple2<Category, List<Board>>>();

		BoardsReader reader = null;

		try {
			reader = this.boardsReaderProvider
					.createBoardsReader(ReaderType.CACHE);

			Tuple2<Category, List<Board>> categoryBoard;
			while ((categoryBoard = reader.read()) != null) {
				categoriesBoards.add(categoryBoard);
			}

			this.boards = categoriesBoards;

			return getBoards();

		} finally {
			IOUtils.closeQuietly(reader);
		}
	}

	@Transactional
	public void update(boolean cache, ProgressMonitor monitor)
			throws IOException, InterruptedException {

		if (monitor == null) {
			monitor = ProgressMonitor.NULL;
		}

		ReaderType readerType = cache ? ReaderType.CONNECT_CACHE
				: ReaderType.CONNECT;

		List<Tuple2<Category, List<Board>>> tmpBoards = new ArrayList<Tuple2<Category, List<Board>>>();

		BoardsReader reader = null;

		try {
			reader = boardsReaderProvider.createBoardsReader(readerType);

			// 桁溢れはしないだろう…
			monitor.beginTask("板一覧の更新", (int) reader.getContentLength());

			Tuple2<Category, List<Board>> categoryBoards;
			while ((categoryBoards = reader.read()) != null) {
				checkCancel(monitor);

				tmpBoards.add(categoryBoards);

				monitor.worked((int) reader.getReadContentLength());

				checkCancel(monitor);
			}

			this.boards = tmpBoards;

		} finally {
			try {
				if (reader != null) {
					reader.close();
				}

			} catch (IOException e) {
				e.printStackTrace();

			} finally {
				monitor.done();
			}
		}
	}

	private void checkCancel(ProgressMonitor monitor)
			throws InterruptedException {

		if (monitor.isCancelled()) {
			throw new InterruptedException("Cancel has been requested.");
		}
	}
}
